/**
 * WebSocket
 */
package com.xiongyingqi.util;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * @author 瑛琪
 * @version 2013-8-7 下午12:09:13
 */
public class EntityHelper {
	// com.kingray.hibernate.domain.KrUser@d0b4b2f[userId=<null>,userName=aaa,userPassword=bbb,
	// a={b, c}]

	private static String reflectToString2(Object object) {
		if (object == null) {
			return null;
		}
		Class clazz = object.getClass();
		Class superClazz = clazz.getSuperclass();

		StringBuilder builder = new StringBuilder(clazz.getName());
		builder.append("@");
		builder.append(object.hashCode());
		builder.append("[");
		Field[] fields = clazz.getDeclaredFields();
		Field[] superFields = superClazz.getDeclaredFields();

		int length = fields.length;
		int countLength = length;
		for (int i = 0; i < length; i++) {
			Field field = fields[i];
			if (Modifier.isStatic(field.getModifiers())) {
				countLength--;
				continue;
			}
			String fieldName = field.getName();
			String methodGet = "get" + fieldName.substring(0, 1).toUpperCase()
					+ fieldName.substring(1, fieldName.length());
			try {
				Method method = clazz.getDeclaredMethod(methodGet);
				try {
					Object value = method.invoke(object);
					builder.append(fieldName);
					builder.append("=");
					if (value == null) {
						builder.append("<null>");
					} else {
						if (value.getClass().isArray()) {
							int arrayLength = Array.getLength(value);
							builder.append("{");
							for (int j = 0; j < arrayLength; j++) {
								Object object2 = Array.get(value, j);
								builder.append(object2.toString());
								if (j < arrayLength - 1) {
									builder.append(", ");
								}
							}
							builder.append("}");
						} else {
							builder.append(value.toString());
						}
					}
					if (i < countLength - 1) {
						builder.append(", ");
					}
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			} catch (SecurityException e) {
			} catch (NoSuchMethodException e) {
			}
		}

		int superLength = superFields.length;
		countLength = superLength;
		for (int i = 0; i < superLength; i++) {
			Field field = superFields[i];
			if (Modifier.isStatic(field.getModifiers())) {
				countLength--;
				continue;
			}
			if (countLength > 0) {
				builder.append(", ");
			}
			String fieldName = field.getName();
			String methodGet = "get" + fieldName.substring(0, 1).toUpperCase()
					+ fieldName.substring(1, fieldName.length());
			try {
				Method method = superClazz.getDeclaredMethod(methodGet);
				try {
					Object value = method.invoke(object);
					builder.append(fieldName);
					builder.append("=");
					if (value == null) {
						builder.append("<null>");
					} else {
						if (value.getClass().isArray()) {
							int arraysuperLength = Array.getLength(value);
							builder.append("{");
							for (int j = 0; j < arraysuperLength; j++) {
								Object object2 = Array.get(value, j);
								builder.append(object2.toString());
								if (j < arraysuperLength - 1) {
									builder.append(", ");
								}
							}
							builder.append("}");
						} else {
							builder.append(value.toString());
						}
					}
					if (i < countLength - 1) {
						builder.append(", ");
					}
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			} catch (SecurityException e) {
			} catch (NoSuchMethodException e) {
			}
		}

		builder.append("]");
		return builder.toString();
	}

	/**
	 * 使用反射机制自动ToString
	 * <br>2013-8-28 下午3:16:40
	 * @param object
	 * @return
	 */
	public static String reflectToString(Object object) {
		if (object == null) {
			return null;
		}
		Class clazz = object.getClass();
		Class superClazz = clazz.getSuperclass();

		StringBuilder builder = new StringBuilder(clazz.getName());
		builder.append("@");
		builder.append(object.hashCode());
		builder.append("[");

		Method[] methods = clazz.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			String methodName = method.getName();
			if (methodName.startsWith("get")
					&& !Modifier.isStatic(method.getModifiers())
					&& Modifier.isPublic(method.getModifiers())) {
				try {
					Object value = method.invoke(object);
					String propertyName = methodName.substring(3, 4)
							.toLowerCase() + methodName.substring(4);
					builder.append(propertyName);
					builder.append("=");

					if (value == null) {
						builder.append("<null>");
					} else {
						if (value.getClass().isArray()) {
							int arraysuperLength = Array.getLength(value);
							builder.append("{");
							for (int j = 0; j < arraysuperLength; j++) {
								Object object2 = Array.get(value, j);
								builder.append(object2.toString());
								if (j < arraysuperLength - 1) {
									builder.append(", ");
								}
							}
							builder.append("}");
						} else {
							builder.append(value.toString());
						}
					}
					builder.append(", ");
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			}
		}
		if(builder.toString().contains(", ")){
			builder.replace(builder.length() - 2, builder.length(), "");
		}

		builder.append("]");
		return builder.toString();
	}

	/**
	 * 简单的ToString方法，只会查找简单类型的数据 <br>
	 * 2013-8-14 下午3:42:01
	 * 
	 * @param object
	 * @return
	 */
	public static String simpleReflectToString(Object object) {
		if (object == null) {
			return null;
		}
		Class clazz = object.getClass();
		Class superClazz = clazz.getSuperclass();

		StringBuilder builder = new StringBuilder(clazz.getName());
		builder.append("@");
		builder.append(object.hashCode());
		builder.append("[");

		Method[] methods = clazz.getDeclaredMethods();
		for (int i = 0; i < methods.length; i++) {
			Method method = methods[i];
			if (!isSimpleType(method.getReturnType())) {
				continue;
			}
			String methodName = method.getName();
			if (methodName.startsWith("get")
					&& !Modifier.isStatic(method.getModifiers())
					&& Modifier.isPublic(method.getModifiers())) {
				try {
					Object value = method.invoke(object);

					String propertyName = methodName.substring(3, 4)
							.toLowerCase() + methodName.substring(4);
					builder.append(propertyName);
					builder.append("=");

					if (value == null) {
						builder.append("<null>");
					} else {
						if (value.getClass().isArray()) {
							int arraysuperLength = Array.getLength(value);
							builder.append("{");
							for (int j = 0; j < arraysuperLength; j++) {
								Object object2 = Array.get(value, j);
								builder.append(object2.toString());
								if (j < arraysuperLength - 1) {
									builder.append(", ");
								}
							}
							builder.append("}");
						} else {
							builder.append(value.toString());
						}
					}
					builder.append(", ");
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			}
		}
		if(builder.toString().contains(", ")){
			builder.replace(builder.length() - 2, builder.length(), "");
		}

		builder.append("]");
		return builder.toString();
	}

	/**
	 * 简单的ToString方法，只会查找简单类型的数据 <br>
	 * 2013-8-14 下午3:42:01
	 * 
	 * @param object
	 * @return
	 */
	private static String simpleReflectToString2(Object object) {
		if (object == null) {
			return null;
		}
		Class clazz = object.getClass();
		Class superClazz = clazz.getSuperclass();

		StringBuilder builder = new StringBuilder(clazz.getName());
		builder.append("@");
		builder.append(object.hashCode());
		builder.append("[");
		Field[] fields = clazz.getDeclaredFields();
		Field[] superFields = superClazz.getDeclaredFields();

		int length = fields.length;
		int countLength = length;
		for (int i = 0; i < length; i++) {
			Field field = fields[i];
			if (Modifier.isStatic(field.getModifiers()) || !isSimpleType(field)) {
				countLength--;
				continue;
			}
			String fieldName = field.getName();
			String methodGet = "get" + fieldName.substring(0, 1).toUpperCase()
					+ fieldName.substring(1, fieldName.length());
			try {
				Method method = clazz.getDeclaredMethod(methodGet);
				try {
					Object value = method.invoke(object);
					builder.append(fieldName);
					builder.append("=");
					if (value == null) {
						builder.append("<null>");
					} else {
						if (value.getClass().isArray()) {
							int arrayLength = Array.getLength(value);
							builder.append("{");
							for (int j = 0; j < arrayLength; j++) {
								Object object2 = Array.get(value, j);
								builder.append(object2.toString());
								if (j < countLength - 1) {
									builder.append(", ");
								}
							}
							builder.append("}");
						} else {
							builder.append(value.toString());
						}
					}
					builder.append(", ");
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			} catch (SecurityException e) {
			} catch (NoSuchMethodException e) {
			}
		}
		if(builder.toString().contains(", ")){
			builder.replace(builder.length() - 2, builder.length(), "");
		}

		int superLength = superFields.length;
		countLength = superLength;
		for (int i = 0; i < superLength; i++) {
			Field field = superFields[i];
			if (Modifier.isStatic(field.getModifiers()) || !isSimpleType(field)) {
				countLength--;
				continue;
			}
			if (countLength > 0) {
				builder.append(", ");
			}
			String fieldName = field.getName();
			String methodGet = "get" + fieldName.substring(0, 1).toUpperCase()
					+ fieldName.substring(1, fieldName.length());
			try {
				Method method = superClazz.getDeclaredMethod(methodGet);
				try {
					Object value = method.invoke(object);
					builder.append(fieldName);
					builder.append("=");
					if (value == null) {
						builder.append("<null>");
					} else {
						if (value.getClass().isArray()) {
							int arraysuperLength = Array.getLength(value);
							builder.append("{");
							for (int j = 0; j < arraysuperLength; j++) {
								Object object2 = Array.get(value, j);
								builder.append(object2.toString());
								if (j < arraysuperLength - 1) {
									builder.append(", ");
								}
							}
							builder.append("}");
						} else {
							builder.append(value.toString());
						}
					}
					if (i < countLength - 1) {
						builder.append(", ");
					}
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			} catch (SecurityException e) {
			} catch (NoSuchMethodException e) {
			}
		}

		builder.append("]");
		return builder.toString();

	}

	public static boolean isSimpleType(Field field) {
		if (field == null) {
			return false;
		}
		return isSimpleType(field.getType());
	}

	public static boolean isSimpleType(Class<?> clazz) {
		if (clazz == null) {
			return false;
		}
		// System.out.println(field.getType().getName());

		if (clazz.equals(Boolean.class)) {
			return true;
		} else if (clazz.equals(Float.class)) {
			return true;
		} else if (clazz.equals(Long.class)) {
			return true;
		} else if (clazz.equals(Double.class)) {
			return true;
		} else if (clazz.equals(Byte.class)) {
			return true;
		} else if (clazz.equals(Integer.class)) {
			return true;
		} else if (clazz.equals(Short.class)) {
			return true;
		} else if (clazz.equals(Character.class)) {
			return true;
		} else if (clazz.equals(BigInteger.class)) {
			return true;
		} else if (clazz.equals(BigDecimal.class)) {
			return true;
		} else if (clazz.equals(String.class)) {
			return true;
		} else if (clazz.equals(boolean.class)) {
			return true;
		} else if (clazz.equals(float.class)) {
			return true;
		} else if (clazz.equals(long.class)) {
			return true;
		} else if (clazz.equals(double.class)) {
			return true;
		} else if (clazz.equals(byte.class)) {
			return true;
		} else if (clazz.equals(int.class)) {
			return true;
		} else if (clazz.equals(short.class)) {
			return true;
		} else if (clazz.equals(char.class)) {
			return true;
		}
		return false;
	}

	/**
	 * 计算对象的hashCode <br>
	 * 2013-8-14 下午3:43:44
	 * 
	 * @param object
	 * @return
	 */
	public static int hashCode(Object object) {
		if (object == null) {
			return 0;
		}

		int hashCode = 17;
		Class clazz = object.getClass();
		Field[] fields = clazz.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			if (Modifier.isStatic(field.getModifiers())) {
				continue;
			}
			String fieldName = field.getName();
			String methodGet = "get" + fieldName.substring(0, 1).toUpperCase()
					+ fieldName.substring(1, fieldName.length());
			try {
				Method method = clazz.getDeclaredMethod(methodGet);
				try {
					Object value = method.invoke(object); // 拥有get方法的参数
					hashCode = hashCode * 31
							+ (value == null ? 0 : value.hashCode());
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			} catch (Exception e) {
			}
		}

		Class<?> superClazz = clazz.getSuperclass();
		Field[] superFields = superClazz.getDeclaredFields();
		for (int i = 0; i < superFields.length; i++) {
			Field field = superFields[i];
			if (Modifier.isStatic(field.getModifiers())) {
				continue;
			}
			String fieldName = field.getName();
			String methodGet = "get" + fieldName.substring(0, 1).toUpperCase()
					+ fieldName.substring(1, fieldName.length());
			try {
				Method method = superClazz.getDeclaredMethod(methodGet);
				try {
					Object value = method.invoke(object); // 拥有get方法的参数
					hashCode = hashCode * 31
							+ (value == null ? 0 : value.hashCode());
				} catch (IllegalArgumentException e) {
				} catch (IllegalAccessException e) {
				} catch (InvocationTargetException e) {
				}
			} catch (Exception e) {
			}
		}

		return hashCode;
	}

	/**
	 * 比较两个对象 <br>
	 * 2013-8-14 下午3:44:00
	 * 
	 * @param origin
	 * @param target
	 * @return
	 */
	public static boolean equals(Object origin, Object target) {
		boolean isEquals = false;
		if (origin == null) {
			if (target == null) {
				isEquals = true;
			} else {
				isEquals = false;
			}
		} else {
			if (target == null) {
				isEquals = false;
			} else { // 两者都不为空
				if (origin.getClass() == target.getClass()) {
					if (origin.hashCode() == target.hashCode()) {
						isEquals = true;
					} else {
						isEquals = false;
					}
				} else {
					isEquals = false;
				}
			}
		}
		return isEquals;
	}

	/**
	 * 打印对象， <br>
	 * 2013-8-26 下午2:45:02
	 * 
	 * @param object
	 */
	public static void printDetail(Object object) {
		StackTraceElement[] stackTraceElements = StackTraceHelper
				.getStackTrace();
		StackTraceElement stackTraceElement = stackTraceElements[2]; // 调用本类的对象类型堆栈
		StringBuilder builder = new StringBuilder();
		builder.append(" ------------------------------------------------------------ ");
		builder.append(StringHelper.line());
		builder.append(StackTraceHelper
				.buildStackTrace(new StackTraceElement[] { stackTraceElement }));
		builder.append("    ");
		if(object == null){
			builder.append("<null>");
		}  else {
			builder.append(object.getClass().getSimpleName());
			builder.append(" =============== ");
			builder.append(reflectToString(object));
		}
		builder.append(StringHelper.line());
		builder.append(" ------------------------------------------------------------ ");
		System.out.println(builder.toString());
	}

	/**
	 * 打印对象， <br>
	 * 2013-8-26 下午2:45:02
	 * 
	 * @param object
	 */
	public static void print(Object object) {
		StackTraceElement[] stackTraceElements = StackTraceHelper
				.getStackTrace();
		StackTraceElement stackTraceElement = stackTraceElements[2]; // 调用本类的对象类型堆栈
		StringBuilder builder = new StringBuilder();
		builder.append(" ------------------------------------------------------------ ");
		builder.append(StringHelper.line());
		builder.append(StackTraceHelper
				.buildStackTrace(new StackTraceElement[] { stackTraceElement }));
		builder.append("    ");
		if(object == null){
			builder.append("<null>");
		} else {
			builder.append(object.getClass().getSimpleName());
			builder.append(" =============== ");
			builder.append(object.toString());
		}
		builder.append(StringHelper.line());
		builder.append(" ------------------------------------------------------------ ");
		System.out.println(builder.toString());
	}

	/**
	 * <br>
	 * 2013-8-8 上午11:36:26
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		return equals(this, obj);
	}

	/**
	 * <br>
	 * 2013-8-8 上午11:16:04
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return hashCode(this);
	}

	/**
	 * <br>
	 * 2013-8-7 下午12:21:49
	 * 
	 * @return
	 */
	private String reflectToString() {
		return reflectToString(this);
	}

	/**
	 * <br>
	 * 2013-8-7 下午12:21:05
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return this.reflectToString();
	}

}
